#include "Spi_Dev_Management/Spi_Dev_Manager.h"
#include "Spi_Dev_Management/Spi_Dev_Factory.h"
#include "Action_Transfer_Cf.h"
#include "Action_Transfer_Df.h"
#include <functional>
#include "rclcpp/rclcpp.hpp"

static rclcpp::Logger TRACE = rclcpp::get_logger("Spi_Dev_Manager");

Spi_Dev_Manager::Spi_Dev_Manager()
    : its_spi_dev(Spi_Dev_Factory::create_spi_dev(Spi_Dev_Platform::Stub, "SPI_Linux"))
    , its_loop_actions(), its_transfer_thread(nullptr)
    , its_statues_poromise(), its_statues_future(its_statues_poromise.get_future()), is_running(false)
{
    its_loop_actions.reserve(2);
}

Spi_Dev_Manager::~Spi_Dev_Manager()
{

}

bool Spi_Dev_Manager::init(Ibuffer_User_Register* buffer_register)
{
    std::unique_ptr<IAction> cf_action = std::make_unique<Action_Transfer_Cf>(its_spi_dev.get(), buffer_register);
    cf_action->register_rx_callback([](const Soc_In_Data_Buffer* ){ });
    its_loop_actions.emplace_back(std::move(cf_action));

    std::unique_ptr<IAction> df_action = std::make_unique<Action_Transfer_Df>(its_spi_dev.get(), buffer_register);
    df_action->register_rx_callback([](const Soc_In_Data_Buffer* ){  });
    its_loop_actions.emplace_back(std::move(df_action));

    its_transfer_thread = std::make_unique<std::thread>(std::bind(&Spi_Dev_Manager::transfer_loop, this));

    return true;
}

bool Spi_Dev_Manager::start()
{
    is_running.store(true);
    its_statues_poromise.set_value(true);

    return true;
}

void Spi_Dev_Manager::stop()
{
    is_running.store(false);
    if(its_transfer_thread && its_transfer_thread->joinable())
    {
        its_transfer_thread->join();
    }
}


void Spi_Dev_Manager::transfer_loop()
{
    if(its_statues_future.valid() && its_statues_future.get())
    {
        while(is_running.load())
        {
            for(auto& action : its_loop_actions)
            {
                action->execute();
            }
        }
    }
    else 
    {
        RCLCPP_ERROR_STREAM(TRACE, "Unknow start command, abort!");
        abort();
    }
    
}
